﻿using System;
using System.Linq;
using System.Runtime.Serialization;
using BrainTechLLC.Communication;
using BrainTechLLC;
using System.Net;
using BrainTechLLC.ThreadSafeObjects;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.Text;
using UserInterface;
using LinFu.AOP.Interfaces;
using BrainTechLLC.Logging;
using Mud.EmlenMudMain;
using System.Web;
using System.Threading;
using System.Diagnostics;

namespace BrainTechLLC.Silverlight.ClientApplication.Web
{
    public class Global : System.Web.HttpApplication
    {
        public static Global _instance;

        public static Communication.PolicySocketServer p = new PolicySocketServer();

        public static void CheckInit()
        {
            try
            {
                string assemblyName;
                Type[] types = Core_RegisterTypes.RegisterTypes();
                TypeProvider.AddTypesForSerialize(types);
                types = TypeProvider_RegisterTypes.RegisterTypes();
                TypeProvider.AddTypesForSerialize(types);
                types = ThreadSafeObjects_RegisterTypes.RegisterTypes(out assemblyName);
                DLLContents contents = TypeProvider.GetInstance().GetDLLContents(assemblyName);
                types.ForEach(type =>
                {
                    if (type.IsTypeOkay())
                        TypeProvider.GetInstance().AddType(contents, type);
                });
                TypeProvider.AddTypesForSerialize(types);
                types = PerceptionAndView_RegisterTypes.RegisterTypes();
                TypeProvider.AddTypesForSerialize(types);
                types = Notification_RegisterTypes.RegisterTypes();
                TypeProvider.AddTypesForSerialize(types);
                types = BasicObjects_RegisterTypes.RegisterTypes();
                TypeProvider.AddTypesForSerialize(types);
                AltSerializeHelper.CheckInit(TypeProvider._typesForSerialize.AllItems);

                GameSetup.CheckInit();
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
                Console.WriteLine(ex.ToString());
            }
        }

        protected void Application_Start(object sender, EventArgs e)
        {
            if (_instance == null)
            {
                if (Interlocked.CompareExchange<Global>(ref _instance, this, null) == null)
                {
                    p.StartSocketServer();
                    Global.CheckInit();
                }
            }
            UsernamesPasswords.EnterGame += new EventHandler<ObjectEventArgs<UsernamePassword>>(UsernamesPasswords_EnterGame);
            UsernamesPasswords.LeaveGame += new EventHandler<ObjectEventArgs<UsernamePassword>>(UsernamesPasswords_LeaveGame);
            Globals.SchedulingEngine.ExceptionOccurred += new EventHandler<ObjectEventArgs<Exception>>(SchedulingEngine_ExceptionOccurred);
            Observable o = GameChar.GetObservableCommands<GameChar>();
            o.NotifyObservers += new EventHandler<ObjectEventArgs<object, object, object, object, object>>(o_NotifyObservers);
        }

        void UsernamesPasswords_LeaveGame(object sender, ObjectEventArgs<UsernamePassword> e)
        {
            var chr = e.obj.CurrentlyPlaying.Find<GameChar>();
            Globals.InGameLog.Log("Leave Game", chr.ShortName + " has left the game.", LogSeverity.Information);
        }

        static void UsernamesPasswords_EnterGame(object sender, ObjectEventArgs<UsernamePassword> e)
        {
            var chr = e.obj.CurrentlyPlaying.Find<GameChar>();
            Globals.InGameLog.Log("Enter Game", chr.ShortName + " has entered the game.", LogSeverity.Information);
        }

        void o_NotifyObservers(object sender, ObjectEventArgs<object, object, object, object, object> e)
        {
            bool before = (bool)e.obj1;
            if (before)
            {
                IInvocationContext ctx = e.obj3 as IInvocationContext;
                GameChar chr = e.obj2 as GameChar;
                GlobalLogger.Log("Command Log", String.Format("{0}: {1}", chr.ShortName, ctx.Arguments[0]), LogSeverity.Information);
            }
        }

        void SchedulingEngine_ExceptionOccurred(object sender, ObjectEventArgs<Exception> e)
        {
            Debug.WriteLine(e.obj.ToString() + Environment.NewLine + e.obj.StackTrace);
            Console.WriteLine(e.obj.ToString() + Environment.NewLine + e.obj.StackTrace);
        }

        protected void Session_Start(object sender, EventArgs e)
        {

        }

        protected void Application_BeginRequest(object sender, EventArgs e)
        {

        }

        protected void Application_AuthenticateRequest(object sender, EventArgs e)
        {

        }

        protected void Application_Error(object sender, EventArgs e)
        {
            Debug.WriteLine("BLAH");
            GlobalLogger.Log(Server.GetLastError(), LogSeverity.Critical, true);
            Server.ClearError();
        }

        protected void Session_End(object sender, EventArgs e)
        {

        }

        protected void Application_End(object sender, EventArgs e)
        {
            GlobalLogger.Log("Application Ended " + System.Web.Hosting.HostingEnvironment.ShutdownReason.ToString(), "Web Application Application_End called", LogSeverity.Critical);
            p.WantExit = true;
            //Thread.Sleep(5000);
        }
    }
}